"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.QQBot = void 0;
const axios_1 = __importDefault(require("axios"));
const formdata_node_1 = require("formdata-node");
const log4js = __importStar(require("log4js"));
const events_1 = require("events");
const sessionManager_1 = require("./sessionManager");
const event_1 = require("./event");
const utils_1 = require("./utils");
class QQBot extends events_1.EventEmitter {
    constructor(config) {
        var _a;
        super();
        this.config = config;
        this.sessionManager = new sessionManager_1.SessionManager(this);
        this.baseUrl = `${((config) => {
          if (config?.ApiUrl?.startsWith('http')) {
             return config.ApiUrl
          } else if (config?.sendbox) {
             return 'https://sandbox.api.sgroup.qq.com'
          } else {
             return 'https://api.sgroup.qq.com'
          }
        })(config)}`;
        this.request = axios_1.default.create({
            baseURL: this.baseUrl,
            timeout: config.timeout || 5000,
            headers: {
                'User-Agent': `BotNodeSDK/0.0.1`
            }
        });
        this.request.interceptors.request.use((config) => {
            config.headers['Authorization'] = `QQBot ${this.sessionManager.access_token}`;
            config.headers['X-Union-Appid'] = this.config.appid;
            if (config['rest']) {
                const restObj = config['rest'];
                delete config['rest'];
                for (const key in restObj) {
                    config.url = config.url.replace(':' + key, restObj[key]);
                }
            }
            if (config.headers['Content-Type'] === 'multipart/form-data') {
                delete config.data.message_reference;
                const formData = new formdata_node_1.FormData();
                for (const key in config.data)
                    if (config.data[key] !== undefined)
                        formData.set(key, config.data[key]);
                config.data = formData;
            }
            return config;
        });
        this.request.interceptors.response.use((res) => res, (res) => {
            if (!res || !res.response || !res.response.data)
                return Promise.reject(res);
            const { code = res?.response.status, message = res?.response.statusText, data } = res?.response?.data || {};
            if ([304023, 304024].includes(code)) {
                this.logger.warn(message);
                return Promise.resolve(res.response.data);
            }
            const err = new Error(`request "${res.config.url}" error with code(${code}): ${message}`);
            return Promise.reject(err);
        });
        this.logger = log4js.getLogger(`[QQBot:${this.config.appid}]`);
        this.logger.level = (_a = this.config).logLevel || (_a.logLevel = 'info');
    }
    removeAt(payload) {
        if (this.config.removeAt === false)
            return;
        const reg = new RegExp(`<@!${this.self_id}>`);
        const isAtMe = reg.test(payload.content) && payload.mentions.some((mention) => mention.id === this.self_id);
        if (!isAtMe)
            return;
        payload.content = payload.content.replace(reg, '').trimStart();
    }
    processPayload(event_id, event, payload) {
        let [post_type, ...sub_type] = event.split('.');
        const result = {
            event_id,
            post_type,
            [`${post_type}_type`]: sub_type.join('.'),
            ...payload
        };
        const parser = event_1.EventParserMap.get(event);
        if (!parser) {
            this.logger.warn('unhandled event', event);
            return result;
        }
        return parser.apply(this, [event, result]);
    }
    dispatchEvent(event, wsRes) {
        this.logger.debug(event, wsRes);
        const payload = wsRes.d;
        const event_id = wsRes.id || '';
        if (!payload || !event)
            return;
        const transformEvent = event_1.QQEvent[event] || 'system';
        try {
            const result = this.processPayload(event_id, transformEvent, payload);
            if (!result)
                return this.logger.debug('解析事件失败', wsRes);
            this.em(transformEvent, result);
        }
        catch (error) {
            return this.logger.debug('解析事件失败', wsRes);
        }
    }
    /**
     * 上传多媒体文件
     * @param target_id 接受者id
     * @param target_type  接受者类型：user|group
     * @param file_data 文件数据：可以是本地文件(file://)或网络地址(http://)或base64或Buffer
     * @param file_type 数据类型：1 image;2 video; 3 audio
     * @returns
     */
    async uploadMedia(target_id, target_type, file_data, file_type, decode = false) {
        file_data = await (0, utils_1.getFileBase64)(file_data);
        const { data: result } = await this.request.post(`/v2/${target_type}s/${target_id}/files`, {
            file_type,
            file_data,
            srv_send_msg: false,
        });
        if (!decode)
            return result;
    }
    em(event, payload) {
        const eventNames = event.split('.');
        const [post_type, detail_type, ...sub_type] = eventNames;
        Object.assign(payload, {
            post_type,
            [`${post_type}_type`]: detail_type,
            sub_type: sub_type.join('.'),
            ...payload
        });
        let prefix = '';
        while (eventNames.length) {
            let fullEventName = `${prefix}.${eventNames.shift()}`;
            if (fullEventName.startsWith('.'))
                fullEventName = fullEventName.slice(1);
            this.emit(fullEventName, payload);
            prefix = fullEventName;
        }
    }
}
exports.QQBot = QQBot;
(function (QQBot) {
    function getFullTargetId(message) {
        switch (message.message_type) {
            case "private":
                return `private-${message.guild_id || message.user_id}`;
            case "group":
                return `group-${message.group_id}:${message.user_id}`;
            case "guild":
                return `guild-${message.channel_id}:${message.user_id}`;
        }
    }
    QQBot.getFullTargetId = getFullTargetId;
})(QQBot || (exports.QQBot = QQBot = {}));
